package main.java.com.waylau.netty.demo.tcppackage;

import java.io.UnsupportedEncodingException;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;

/**
 * 作者  Administrator
 * 时间  2017/6/26 17:58
 * 文件  nettydemo
 * 描述  https://my.oschina.net/stefanzhlg/blog/378103
 */
public class TimeClient {
	public void connect(int port, String host) throws InterruptedException {
		EventLoopGroup group = new NioEventLoopGroup();
		try {
			Bootstrap b = new Bootstrap();
			b.group(group).channel(NioSocketChannel.class)
					.option(ChannelOption.TCP_NODELAY, true)
					.handler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel arg0) throws Exception {
							arg0.pipeline().addLast(new LineBasedFrameDecoder(1024));
							arg0.pipeline().addLast(new StringDecoder());
							arg0.pipeline().addLast(new TimeClientHandler());
						}

					});

			ChannelFuture f = b.connect(host, port).sync();
			f.channel().closeFuture().sync();

		} finally {
			group.shutdownGracefully();
		}
	}

	public static void main(String[] args) throws InterruptedException {
		int port = 8080;
		if (args != null && args.length > 0) {
			port = Integer.valueOf(args[0]);
		}
		new TimeClient().connect(port, "127.0.0.1");
	}

	class TimeClientHandler extends ChannelInboundHandlerAdapter {

		private int counter;

		private byte[] req;

		public TimeClientHandler() {
//			req = ("Query time order " + System.getProperty("line.separator")).getBytes();
			req = ("Query time order " + System.getProperty("line.separator")).getBytes();
		}

		private StringBuilder stringBuilder = new StringBuilder();

		/**
		 * @param ctx 第一次发送最大帧长内的数据包
		 * @throws Exception 第二次发送超过帧长的包 丢包
		 * 第三次发送正常的包
		 *
		 * 预期结果：收到两个正常包
		 */
		@Override
		public void channelActive(ChannelHandlerContext ctx) throws Exception {
			super.channelActive(ctx);
			ByteBuf message = null;
//			========第一波数据==================
			String msg1 = "Query time order 1";
			message = Unpooled.buffer((msg1+ System.getProperty("line.separator")).getBytes().length);
			message.writeBytes((msg1 + System.getProperty("line.separator")).getBytes());
			ctx.writeAndFlush(message);
//			========第二波数据===================
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < 6; i++) {
				stringBuilder.append("Query time order2");
			}

			String msg2 = stringBuilder.toString();
			message = Unpooled.buffer((msg2+ System.getProperty("line.separator")).getBytes().length);
			message.writeBytes((msg2 + System.getProperty("line.separator")).getBytes());
			ctx.writeAndFlush(message);

//          =========第三波数据=====================
			String msg3 = "Query time order 3";
			message = Unpooled.buffer((msg3+ System.getProperty("line.separator")).getBytes().length);
			message.writeBytes((msg3 + System.getProperty("line.separator")).getBytes());
			ctx.writeAndFlush(message);

		}
		/*		@Override
		public void channelActive(ChannelHandlerContext ctx) {
			ByteBuf message = null;
			//连续发送100个包 56 一次  113两次  170 收三次
			//第一次只发了16字节
			//后面的几次肯定超过了20字节
			for (int i = 0; i < 8; i++) {
				stringBuilder.append("Query time order");
				if (i%6==0){
					stringBuilder.append(System.getProperty("line.separator"));
					message = Unpooled.buffer(stringBuilder.length());
					message.writeBytes(stringBuilder.toString().getBytes());
					ctx.writeAndFlush(message);
					stringBuilder = new StringBuilder();
				}
			*//*	message = Unpooled.buffer(req.length);
				message.writeBytes(req);
				ctx.writeAndFlush(message);*//*
//				try {
//					Thread.sleep(1000);
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
			}
		}*/

		/**
		 * @param ctx
		 * .0
		 * @param msg 每次从TCP缓存中读一下，都会调用channelRead方法
		 * @throws UnsupportedEncodingException
		 * 实验是：channelRead 只被触发了一次啊 (是不是说TCP缓存比较大)
		 */
		@Override
		public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException {
			System.out.println("Client:" + ++counter);
			ByteBuf buf = (ByteBuf) msg; // TCP 的缓存会不断的读取到msg 中
			byte[] req = new byte[buf.readableBytes()];
			buf.readBytes(req);
//			String body = new String(req, "UTF-8");
//			String sb = body.substring(0,body.length()-System.getProperty("line.separator").length());
//			System.out.println("Now is :" + sb + ";the counter is :" + ++counter);

		}


		/**
		 * @param ctx 这里只能说明我读取完了，并不能说明我发送完了啊
		 * @throws Exception
		 */
		@Override
		public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
			super.channelReadComplete(ctx);
		}

		@Override
		public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
			super.exceptionCaught(ctx, cause);
			ctx.close();
		}

	}
}
